﻿using Microsoft.Xna.Framework;
using RaptorEngine;
using RaptorEngine.Components;
using RaptorEngine.Components.CollidableComponent;

namespace OilRigSumoWrestlers.Actions
{
    internal class ExplosionAction : CollisionAction
    {
        private float _force;
        private Entity firstVictim;
        private bool hasExploded = false;
        private bool hasRunUpdate = false;

        public ExplosionAction(float force)
        {
            _force = force;
        }

        /// <summary>
        /// Handles collision between two boundingSpheres with newton physics solid spheres and no energy wasted. 
        /// </summary>
        /// <param name="ownEntity">The parent entity of the action</param>
        /// <param name="ownVolume">The parent bounding volume of the action</param>
        /// <param name="othersEntity">The other colliding entity</param>
        /// <param name="othersVolume">The boundingVolume of the other entity</param>
        /// <param name="gameTime"></param>
        public override void HandleCollision(Entity ownEntity, BoundingVolume ownVolume, Entity othersEntity,
                                             BoundingVolume othersVolume)
        {
            Movable moveable = null;
            if (othersEntity.HasComponent(ComponentType.Movable))
            {
                if (hasExploded)
                    hasRunUpdate = true;

                moveable = (Movable) othersEntity.GetComponent(ComponentType.Movable);
                if (firstVictim == null)
                {
                    firstVictim = othersEntity;
                    PerformExplosion(ownEntity, ownVolume, othersVolume, moveable);
                    hasExploded = true;
                }
                else if (firstVictim != othersEntity)
                {
                    PerformExplosion(ownEntity, ownVolume, othersVolume, moveable);
                }

                if (hasExploded && hasRunUpdate)
                {
                    GameEngine.Instance.Scene.PeekScene().RemoveEntity(ownEntity);
                }
            }
        }

        private void PerformExplosion(Entity ownEntity, BoundingVolume ownVolume, BoundingVolume othersVolume, Movable moveable)
        {
            Vector3 pushDir = new Vector3(
                othersVolume.Center.X - ownVolume.Center.X,
                /*othersVolume.Center.Y - ownVolume.Center.Y*/0,
                othersVolume.Center.Z - ownVolume.Center.Z);
            pushDir.Normalize();

            //Figure out the distance to center
            float distance = Vector3.Distance(ownVolume.Center, othersVolume.Center);

            // Being closer means more force
            float explosionModifier = _force / distance;

            if (distance < 1)
                explosionModifier = _force;

            moveable.Velocity = new Vector3(
                moveable.Velocity.X + (pushDir.X * explosionModifier),
                moveable.Velocity.Y + (pushDir.Y * explosionModifier),
                moveable.Velocity.Z + (pushDir.Z * explosionModifier));

			if(ownEntity.HasComponent(ComponentType.Particle))
			{
				ParticleComp part = (ParticleComp)ownEntity.GetComponent(ComponentType.Particle);
				GameEngine.Instance.Scene.PeekScene().Camera.Shake(1f, 4f);
				for (int i = 0; i < 40; i++)
				{
					if (i < 5)
					{
						part.AddParticles("explosion", ownEntity.Position, Vector3.Zero);
					}
					else
					{
						part.AddParticles("bouncingSmoke", ownEntity.Position, Vector3.Zero);
					}
				}
			}
		}
    }
}
